package tum0r.webengine.main

import com.alibaba.fastjson.util.TypeUtils
import tum0r.webengine.annotations.scan.ScanAnnotations
import tum0r.webengine.command.ExecuteCommand
import tum0r.webengine.config.BaseConfig
import tum0r.webengine.config.LogFileConfig
import tum0r.webengine.core.Server
import tum0r.webengine.core.handle.AfterResponse
import tum0r.webengine.core.handle.Filter
import tum0r.webengine.enums.EConfigType
import tum0r.webengine.enums.EGenerateType
import tum0r.webengine.extension.check
import tum0r.webengine.extension.threadExecute
import tum0r.webengine.models.database.DatabaseConnect
import java.io.File


fun banLogFile() {
    BaseConfig.setState(EConfigType.SAVE_INFO_LOG_TO_FILE, flag = false, quiet = true)
    BaseConfig.setState(EConfigType.SAVE_ERROR_LOG_TO_FILE, flag = false, quiet = true)
}

/**
 * 说明: 服务器运行类
 *
 * 创建者: tum0r
 *
 * 时间: 2021/8/18 16:54
 */
class Program {
    // region 日志设置

    /**
     * 设置日志文件
     *
     * @param[index] 日志文件类型
     * @param[file] 日志文件
     */
    fun setLogFile(index: Int, file: File) = Setting.setLogFile(index, file)

    /**
     * 设置日志文件
     *
     * @param[index] 日志文件类型
     * @param[path] 日志文件路径
     */
    fun setLogFile(index: Int, path: String) {
        if (path.check("日志文件路径")) Setting.setLogFile(index, File(path))
    }

    /**
     * 设置日志文件
     *
     * @param[index] 日志文件类型
     * @param[file] 日志文件
     */
    fun setOldLogFile(index: Int, file: File) = Setting.setLogFile(index, file, LogFileConfig.OLD_LOG_FILES, "旧日志")

    /**
     * 设置日志文件
     *
     * @param[index] 日志文件类型
     * @param[path] 日志文件路径
     */
    fun setOldLogFile(index: Int, path: String) {
        if (path.check("旧日志文件路径")) Setting.setLogFile(index, File(path))
    }

    // endregion

    // region 扫描包设置

    /**
     * 设置扫描接口的包名
     *
     * @param[packageName] 包名
     */
    fun setScanServersPackage(packageName: String) = Setting.setScanServersPackage(packageName)

    /**
     * 设置扫描命令的包名
     *
     * @param[packageName] 包名
     */
    fun setScanCommandsPackage(packageName: String) = Setting.setScanCommandsPackage(packageName)

    /**
     * 设置扫描数据库表的包名
     *
     * @param[packageName] 包名
     */
    fun setScanTablesPackage(packageName: String) = Setting.setScanTablesPackage(packageName)

    // endregion

    /**
     * 添加请求过滤规则
     *
     * @param[filter] 过滤规则
     */
    fun addFilter(filter: Filter) = Setting.addFilter(filter)

    /**
     * 添加响应完请求后要进行的处理
     *
     * @param[afterResponse] 要进行的处理
     */
    fun addAfterResponse(afterResponse: AfterResponse) = Setting.addAfterResponse(afterResponse)

    /**
     * 添加数据库信息
     *
     * @param[info] 数据库连接信息
     */
    fun addDatabaseInfo(info: DatabaseConnect) = Setting.addDatabaseInfo(info)

    /**
     * 修改网站图标
     *
     * @param[index] 0 Safari浏览器 1 其他浏览器
     * @param[file] 网站图标文件，为null恢复默认
     * @param[mapping] 网站图标映射路径
     */
    fun changeIcon(index: Int, file: File?, mapping: String) = Setting.changeIcon(index, file, mapping)

    /**
     * 生成代码
     *
     * @param[type] 生成代码类型
     * @param[targetPath] 生成代码路径
     * @param[packageName] 生成代码包名
     */
    fun generateCode(type: EGenerateType, targetPath: String, packageName: String?) = GenerateCode.generateCode(type, targetPath, packageName)

    /**
     * 启动服务器
     */
    fun start(args: Array<String>) {
        // 不显示警告信息
        Setting.disableWarning()
        // 变量首字母不转小写
        TypeUtils.compatibleWithJavaBean = true

        // 移动到旧日志文件
        LogFileConfig.move(0, EConfigType.MOVE_INFO_OLD_LOG)
        LogFileConfig.move(1, EConfigType.MOVE_DEBUG_OLD_LOG)
        LogFileConfig.move(2, EConfigType.MOVE_ERROR_OLD_LOG)

        // 打开日志文件记录
        LogFileConfig.open()

        val scanAnnotations = ScanAnnotations()
        // 扫描请求接口、命令和数据库表
        scanAnnotations.scanCommands()
        scanAnnotations.scanServers()
        scanAnnotations.scanTables()

        // 执行初始化命令
        val executeCommand = ExecuteCommand()
        for (command in args) executeCommand.exec(command)

        // 启动服务器
        val server = Server()
        threadExecute(server)

        // 执行输入的命令
        while (BaseConfig.isState(EConfigType.SERVER_IS_OPEN)) readLine()?.let { executeCommand.exec(it.trim()) }

        // 关闭服务器
        server.close()
    }
}